Terraform CloudでSentinelを使ってPolicy as Codeやってみた
「Terraform Cloudを使って、Policy as Codeでガバナンスを効かせたい」
Terraform Cloudの魅力的な機能の一つにSentinelやOPAを使って作成したポリシーを簡単に適用できることがあると思います。
今回は、Sentinelを使ったポリシー作成とワークスペースへのポリシー適用の流れについて書きます。
Terraform CloudのPolicy as Code
Terraform CloudではTeam & Governance以上のプランでSentinelやOPAを使ったポリシーを、組織やワークスペースに適用できる機能があります。
この機能を使うことで、Terraform Cloud上でインフラを作成する際にポリシーに違反している場合はデプロイできないといったことが可能です。
ポリシーの例)
- EC2インスタンスのインスタンスサイズがt2.micro~mediumのみ作成を許可
- Nameタグがついていないインスタンスは作成不可
- 作成するリソースのコストが100USD/月未満の場合は許可
Install the Sentinel CLI | Terraform | HashiCorp Developer
上記のようなポリシーをTerraform Cloud上でPolicy Setとして登録して使用します。
Policy Setの概要は以下です。
図中はPolicy Setを1つのWork Spaceに関連づけているますが複数のワークスペースや組織自体に関連づけることも可能です。
Terraform Cloud Policy Set適用の流れ
Terraform CloudでPolicy Setを適用する流れを、説明していきます。 Terraform Cloudのチュートリアルを参考にしています。
ローカルにSentinel CLIをインストール
ローカルにSentinel CLIをインストールします。
Sentinel CLIを実行するためにTerraform Planのデータが必要なため、次のステップでデータを取得します。
Install the Sentinel CLI | Terraform | HashiCorp Developer
既存のワークスペースからMock Dataを取得
データの取得は簡単です。既存のワークスペースからRuns
>Download Sentinel mocks
を選択するだけです。
Generate Policy Mock Data | Terraform | HashiCorp Developer
mock*.sentinelというファイルがいくつかダウンロードできると思います。 plan・run・configといった形で、それぞれにポリシールールを定義できます。(今回は次のステップでplanを使用しています)
ダウンロードしたファイルの情報は、sentinel.hcl
にも書かれています。
mock "tfconfig" { module { source = "mock-tfconfig.sentinel" } } mock "tfconfig/v1" { module { source = "mock-tfconfig.sentinel" } } mock "tfconfig/v2" { module { source = "mock-tfconfig-v2.sentinel" } } mock "tfplan" { module { source = "mock-tfplan.sentinel" } } mock "tfplan/v1" { module { source = "mock-tfplan.sentinel" } } mock "tfplan/v2" { module { source = "mock-tfplan-v2.sentinel" } } mock "tfstate" { module { source = "mock-tfstate.sentinel" } } mock "tfstate/v1" { module { source = "mock-tfstate.sentinel" } } mock "tfstate/v2" { module { source = "mock-tfstate-v2.sentinel" } } mock "tfrun" { module { source = "mock-tfrun.sentinel" } }
Generate Policy Mock Data | Terraform | HashiCorp Developer
ローカルでPolicyを作成・テストする
ポリシー作成に必要なファイルをサンプルリポジトリを例に説明します。
sentinel.hcl
Sentinelの設定を定義しています。
先程ダウンロードしたファイルの中にあった、sentinel.hcl
です。
必要な部分だけ残して他を削除します。
mock "tfplan/v2" { module { source = "mock-tfplan-v2.sentinel" } }
restrict-aws-instances-type-and-tag.sentinel
ポリシーを定義するファイルです。 今回は、Nameタグ・EC2インスタンスタイプのポリシーを定義しています。
# Imports mock data import "tfplan/v2" as tfplan # Get all AWS instances from all modules ec2_instances = filter tfplan.resource_changes as _, rc { rc.type is "aws_instance" and (rc.change.actions contains "create" or rc.change.actions is ["update"]) } # Mandatory Instance Tags mandatory_tags = [ "Name", ] # Allowed Types allowed_types = [ "t2.micro", "t2.small", "t2.medium", ] # Rule to enforce "Name" tag on all instances mandatory_instance_tags = rule { all ec2_instances as _, instance { all mandatory_tags as mt { instance.change.after.tags contains mt } } } # Rule to restrict instance types instance_type_allowed = rule { all ec2_instances as _, instance { instance.change.after.instance_type in allowed_types } } # Main rule that requires other rules to be true main = rule { (instance_type_allowed and mandatory_instance_tags) else true }
mock-tfplan-v2.sentinel
作成したポリシーのテストに使用します。(長いため、抜粋しています。)
resource_changes = { "aws_instance.ubuntu": { "address": "aws_instance.ubuntu", "change": { ## ... "after": { ## .. "tags": { "Name": "Provisioned by Terraform", }, ## .. } ## ... }, ## ... }, }
Policyのテスト
ポリシーのテストは以下のコマンドで実行できます。
$ sentinel apply restrict-aws-instances-type-and-tag.sentinel Pass - restrict-aws-instances-type-and-tag.sentinel
Write a Sentinel Policy for a Terraform Deployment | Terraform | HashiCorp Developer
Terraform CloudでPolicy Setを作成する
Policyのテストが完了したら、実際にTerraform Cloud上で使用してみます。
sentinel.hcl
にenforcement_level
の設定を追加します。
この設定でポリシーに対する寛容度を設定することができます。
policy "restrict-aws-instances-type-and-tag" { enforcement_level = "hard-mandatory" } mock "tfplan/v2" { module { source = "mock-tfplan-v2.sentinel" } }
例) - ポリシー違反していても、ログに残してTerraformの実行を許可 - ポリシー違反していたら、Terraform実行を拒否
詳しくは以下をご確認ください。
Upload Your Sentinel Policy Set to Terraform Cloud | Terraform | HashiCorp Developer
上記の変更が完了してGithubにも反映したらTerraform Cloudのコンソールから、Policy Setsを選択します。 ワークスペースを作る時と同様に、Githubリポジトリと接続することができます。
Policyの適用範囲を設定して、Policy Sets作成します。
Policy Setをワークスペースに適用して、実行されることを確認する
最後にPolicyが適用されているかをワークスペースで確認します。
ルール外のインスタンスサイズで作成しようとすると、以下のようにポリシーでエラーが出ます。
インスタンスサイズ変更後は、Apply可能な状態になりました。
Control Costs with Policies | Terraform | HashiCorp Developer
おわりに
Terraform CloudでSentinelを使ったPolicy適用でした。
Terraformリポジトリが複数ある場合、Policyを一括して適用するのは少し手間がかかるかもしれません。
Terraform Cloudを使用すれば、簡単に組織やワークスペースに対してPolicyを適用できて運用を楽にできそうです。
以上、AWS事業本部の佐藤(@chari7311)でした。